home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Publishing
/
ImagePortfolio
/
Source
/
ImagePortfolio.m
< prev
next >
Wrap
Text File
|
1994-04-01
|
14KB
|
468 lines
// -------------------------------------------------------------------------------------
// ImagePortfolio.m - Visual TIFF/EPS file manager
// Author: Martin D. Flynn
// You may freely copy, distribute and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to its
// fitness for any particular use.
// -------------------------------------------------------------------------------------
#import <libc.h>
#import <stdlib.h>
#import <stdio.h>
#import <string.h>
#import <mach/mach.h>
#import <objc/List.h>
#import <objc/objc-runtime.h>
#import <objc/NXBundle.h>
#import <defaults/defaults.h>
#import <dpsclient/wraps.h>
#import <appkit/Window.h>
#import <appkit/Panel.h>
#import <appkit/OpenPanel.h>
#import <appkit/Text.h>
#import <appkit/TextField.h>
#import <appkit/Button.h>
#import <appkit/Matrix.h>
#import <appkit/Font.h>
#import <appkit/ScrollView.h>
#import <appkit/Speaker.h>
#import <appkit/Listener.h>
#import <appkit/Menu.h>
#import <appkit/MenuCell.h>
#import <appkit/graphics.h>
#import <appkit/publicWraps.h>
#import <appkit/NXImage.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/NXEPSImageRep.h>
#import "GifImageRep.h"
#import "ImagePortfolio.h"
#import "Portfolio.h"
#import "PaletteCell.h" // for adding support image types
#import "PaletteMatrix.h"
// -------------------------------------------------------------------------------------
// version number
#define versionNUMBER "1.30"
// -------------------------------------------------------------------------------------
// This is done for the purpose of allowing to setDelegate on the appIcon window
// [DelegateWindow poseAs:[Window class]] must be issued in +new(Application)
@interface DelegateWindow:Window @end
@implementation DelegateWindow
- setDelegate:sender
{
if ((wFlags.style != NX_TOKENSTYLE) && (wFlags.style != NX_MINIWORLDSTYLE)) {
[super setDelegate:sender];
} else {
int saveStyle = wFlags.style;
wFlags.style = NX_PLAINSTYLE;
[super setDelegate:sender];
wFlags.style = saveStyle;
}
return self;
}
@end
// -------------------------------------------------------------------------------------
@implementation ImagePortfolio
// -------------------------------------------------------------------------------------
// menu/button actions
/* make and show new image Palette */
- newImagePalette:sender
{
return [[Portfolio alloc] initFromFile:(char*)nil];
}
/* open Palette file */
- open:sender
{
id pOpen;
char fName[MAXPATHLEN+1], *dir, **files, *fTypes[] = { docEXTENSION, 0 };
/* build/display open panel */
pOpen = [OpenPanel new];
[pOpen setTitle:"Open Image Portfolio"];
[pOpen setPrompt:"File:"];
[pOpen setRequiredFileType:fTypes[0]];
[pOpen allowMultipleFiles:YES];
[pOpen setDirectory:[NXApp lastPath]];
if (![pOpen runModalForTypes:fTypes]) return self;
/* open the list of selected files */
if (!(files = (char**)[pOpen filenames])) return self;
if (dir=(char*)[pOpen directory]) { chdir(dir); [self setLastPath:dir]; }
while (*files) {
sprintf(fName, "%s/%s", dir, *files++);
[[Portfolio alloc] initFromFile:fName];
}
return self;
}
/* arrange windows in front */
- arrangeInFront:sender
{
return self;
}
/* show info panel */
- showInfo:sender
{
return [infoPanel makeKeyAndOrderFront:sender];
}
/* show help panel */
- showHelp:sender
{
return [helpPanel makeKeyAndOrderFront:sender];
}
/* show preferences panel (to be called by PaletteMatrix only!) */
- showPreferences:sender
{
id winDel = [Portfolio activePortfolio];
int rows, cols;
/* exit if not proper portfolio type (must match sender) */
if (!winDel || ![winDel isKindOf:[Portfolio class]]) return self;
/* set screen fields */
[fontName setStringValue:[[winDel font] name]];
[fontSize setFloatValue:[[winDel font] pointSize]];
[prefCellWidth setFloatValue:[winDel cellSize]->width ];
[prefCellHeight setFloatValue:[winDel cellSize]->height];
[winDel getDisplayedRows:&rows cols:&cols];
[prefCellRows setIntValue:rows];
[prefCellColumns setIntValue:cols];
/* show window */
[prefPanel makeKeyAndOrderFront:sender];
[NXApp runModalFor:prefPanel];
return self;
}
/* cancel preferences */
- cancelPreferences:sender
{
[NXApp stopModal:0];
[prefPanel orderOut:sender];
return self;
}
/* save preference to defaults table */
- saveDefaults:sender
{
id winDel = [Portfolio activePortfolio];
if (winDel && [winDel isKindOf:[Portfolio class]]) [winDel saveDefaults:sender];
return self;
}
/* print key window */
- printKeyWindow:sender
{
return (keyWindow)? [keyWindow smartPrintPSCode:sender] : (id)nil;
}
// -------------------------------------------------------------------------------------
// return application constants
/* set last default saved/openned file path */
- setLastPath:(char*)path
{
return [self setLastPathNoCopy:NXCopyStringBuffer(path)];
}
/* set last default saved/openned file path */
- setLastPathNoCopy:(char*)path
{
if (lastPath) free(lastPath);
lastPath = path;
return self;
}
/* return last saved/openned path */
- (const char*)lastPath
{
return (lastPath)? lastPath : NXHomeDirectory();
}
// -------------------------------------------------------------------------------------
// inline event dispatcher
// - When this method is interleaved with other methods, such as loading a large image
// directory, this allows continued interaction with the user.
- dispatchEvents
{
NXEvent *e;
while (e=[NXApp getNextEvent:NX_MOUSEDOWNMASK waitFor:0.0 threshold:NX_BASETHRESHOLD])
[NXApp sendEvent:e];
return self;
}
// -------------------------------------------------------------------------------------
// menu cell update handler methods
- _setMenuCellsUpdateAction:menuId
{
id cellList = [[menuId itemList] cellList];
int i = [cellList count];
while(i) {
id cell = [cellList objectAt:--i];
SEL updAct, cSel = [cell action];
if ([cell hasSubmenu]) { [self _setMenuCellsUpdateAction:[cell target]]; continue; }
if ([cell target]) continue;
updAct = @selector(_ucKeyWindow:); // default updateAction
if (cSel==@selector(cut:) ) updAct=@selector(_ucCutCopyDelete:); else
if (cSel==@selector(copy:) ) updAct=@selector(_ucCutCopyDelete:); else
if (cSel==@selector(delete:) ) updAct=@selector(_ucCutCopyDelete:); else
if (cSel==@selector(undelete:) ) updAct=@selector(_ucUndelete:); else
if (cSel==@selector(paste:) ) updAct=@selector(_ucResponder:); else
if (cSel==@selector(save:) ) updAct=@selector(_ucSelectable:); else
if (cSel==@selector(saveAs:) ) updAct=@selector(_ucSelectable:); else
if (cSel==@selector(print:) ) updAct=@selector(_ucSelectable:); else
if (cSel==@selector(selectAll:) ) updAct=@selector(_ucSelectable:); else
if (cSel==@selector(sortByCellTitle:) ) updAct=@selector(_ucSelectable:); else
if (cSel==@selector(showPreferences:) ) updAct=@selector(_ucMainWindow:); else
if (cSel==@selector(performClose:) ) updAct=@selector(_ucKeyWindow:); else
if (cSel==@selector(performMiniaturize:)) updAct=@selector(_ucKeyWindow:); else
if (cSel==@selector(printKeyWindow:) ) updAct=@selector(_ucKeyWindow:);
[cell setUpdateAction:updAct forMenu:menuId];
[menuId setAutoupdate:YES];
}
return self;
}
/* return menuCell responder */
- _cellResponder:cellId
{
id respId = (keyWindow)? [keyWindow firstResponder] : (id)nil;
return (respId && [respId respondsTo:[cellId action]])? respId : (id)nil;
}
/* return menuCell enabling flag */
- (BOOL)_cellEnabler:cellId :(SEL)meth
{
id respId = [self _cellResponder:cellId];
[cellId setEnabled:((respId&&[respId respondsTo:meth]&&[respId perform:meth])?YES:NO)];
return YES;
}
/* print/save/saveAs/selectAll: cells selectable */
- (BOOL)_ucSelectable:cellId
{
return [self _cellEnabler:cellId :@selector(anySelectableCells)];
}
/* cut/copy/delete */
- (BOOL)_ucCutCopyDelete:cellId
{
return [self _cellEnabler:cellId :@selector(selectedCell)];
}
/* undelete */
- (BOOL)_ucUndelete:cellId
{
return [self _cellEnabler:cellId :@selector(undeletable)];
}
/* keyWindow menu cell update method */
- (BOOL)_ucKeyWindow:cellId
{
[cellId setEnabled:(keyWindow?YES:NO)];
return YES;
}
/* mainWindow menu cell update method */
- (BOOL)_ucMainWindow:cellId
{
[cellId setEnabled:(mainWindow?YES:NO)];
return YES;
}
/* paste */
- (BOOL)_ucResponder:cellId
{
[cellId setEnabled:([self _cellResponder:cellId]?YES:NO)];
return YES;
}
// -------------------------------------------------------------------------------------
// application delegate
/* Application instantiation */
+ new
{
[DelegateWindow poseAs:[Window class]];
return [super new];
}
/* application initialization */
- appDidInit:sender
{
NXAtom pbsTypes[1];
/* clear vars */
lastPath = (char*)nil;
/* set the first responder update actions */
[self setAutoupdate:YES];
[self _setMenuCellsUpdateAction:[NXApp mainMenu]];
/* set version number */
[versionNum setStringValue:versionNUMBER];
/* add supported image file types */
[PaletteCell addImageClass:[GifImageRep class] , ".gif" , (char*)nil];
[PaletteCell addImageClass:[NXBitmapImageRep class] , ".tiff", ".icon" , (char*)nil];
[PaletteCell addImageClass:[NXEPSImageRep class] , ".eps", ".ps", ".ai", (char*)nil];
/* center information panel */
[infoPanel center];
[helpPanel center];
[prefPanel center];
/* make app active */
[NXApp activateSelf:YES];
/* find real appIcon local window number and register for dragging */
[[NXApp appIcon] setDelegate:self];
NXConvertWinNumToGlobal([[NXApp appIcon] windowNum], &appIconWinNum);
NXConvertGlobalToWinNum(appIconWinNum, &appIconWinNum);
pbsTypes[0] = NXFilenamePboardType;
[[NXApp appIcon] registerForDraggedTypes:pbsTypes count:1];
return self;
}
/* application termination (check windows for unsaved files) */
- appWillTerminate:sender
{
/* display panel if unsaved files are found */
if ([Portfolio isDocEdited]) {
int rtn;
const char *msg, *quit, *qAny, *cncl;
msg = NXLocalizedString("There are edited windows.", (char*)nil,(char*)nil);
quit = NXLocalizedString("Quit", (char*)nil,(char*)nil);
qAny = NXLocalizedString("Quit Anyway", (char*)nil,(char*)nil);
cncl = NXLocalizedString("Cancel", (char*)nil,(char*)nil);
rtn = NXRunAlertPanel(quit, msg, qAny, cncl, (char*)nil);
if (rtn == NX_ALERTALTERNATE) return (id)nil;
}
/* MUST unregister appIcon window, otherwise drag may fail next time app is launched */
[[NXApp appIcon] unregisterDraggedTypes];
/* return */
return self;
}
/* indicate to Workspace Manager that I accept files */
- (BOOL)appAcceptsAnotherFile:sender { return YES; }
/* open a Workspace Manager provided file */
- (int)appOpenFile:(char*)filename type:(char*)type
{
[[Portfolio alloc] initFromFile:filename];
return YES;
}
// -------------------------------------------------------------------------------------
// application icon window delegate
// - This section handles files dragged and dropped onto the application icon
static char iconFiles[MAXPATHLEN + 1] = { 0 };
/* set dock icon to specified image */
- _setDockIcon:image
{
id iconWin = [NXApp appIcon];
NXPoint iconOrigin = { 0.0, 0.0 };
NXSize imageSize;
static id tileImage = (id)nil;
static NXSize tileSize = { 0.0, 0.0 };
/* init dock icon tile */
if (!tileImage && (tileImage = [NXImage findImageNamed:"NXAppTile"])) {
[tileImage getSize:&tileSize];
}
/* draw background tile */
[[iconWin contentView] lockFocus];
PSsetinstance(FALSE);
[tileImage composite:NX_COPY toPoint:&iconOrigin];
[tileImage getSize:&tileSize];
[image getSize:&imageSize];
iconOrigin.x = (tileSize.width - imageSize.width ) / 2.0;
iconOrigin.y = (tileSize.height - imageSize.height) / 2.0;
[image composite:NX_SOVER toPoint:&iconOrigin];
[[iconWin contentView] unlockFocus];
[iconWin display];
return self;
}
/* files entered icon window */
// - save the list of file names and the representing icon image
- (NXDragOperation)draggingEntered:sender
{
char *fileList;
int fileListLen;
Pasteboard *pb = [sender draggingPasteboard];
static id openFolder = (id)nil;
if (!openFolder) openFolder = [NXImage findImageNamed:"openFolder"];
if ([pb readType:NXFilenamePboardType data:&fileList length:&fileListLen]) {
strcpy(iconFiles, fileList);
[self _setDockIcon:openFolder];
return NX_DragOperationCopy;
}
return NX_DragOperationNone;
}
/* mouse exited icon window */
- draggingExited:sender
{
static id dockIcon = (id)nil;
if (!dockIcon) dockIcon = [NXImage findImageNamed:"app"];
[self _setDockIcon:dockIcon];
return self;
}
/* indicate we accept dragging */
- (BOOL)prepareForDragOperation:sender
{
if (!*iconFiles) return NO;
return YES;
}
/* files dropped in icon window */
- (BOOL)performDragOperation:sender
{
if (!*iconFiles) return NO;
[NXApp activateSelf:YES];
[[Portfolio alloc] initFromFile:iconFiles];
[self draggingExited:(id)nil];
return YES;
}
/* find window for number (special case for appIcon window) */
- findWindow:(int)windowNum
{
return (windowNum == appIconWinNum)? [NXApp appIcon] : [super findWindow:windowNum];
}
/*
- (int)dragEnter:(int)windowNum x:(double)x y:(double)y iconOffsetX:(double)hx iconOffsetY:(double)hy iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY iconWidth:(double)iconWidth iconHeight:(double)iconHeight sequenceNumber:(int)seqNum pasteboardName:(char *)pbName operationMask:(int)opMask operation:(int *)op
{
int gWin;
NXConvertGlobalToWinNum(windowNum, &gWin);
printf("dragEnter...(%d/%d)(%d/%d)\n", windowNum, gWin,
appIconWinNum, [[NXApp appIcon] windowNum]);
return (int)[super dragEnter:windowNum x:x y:y iconOffsetX:hx iconOffsetY:hy iconWindow:iconWindowNum iconX:iconX iconY:iconY iconWidth:iconWidth iconHeight:iconHeight sequenceNumber:seqNum pasteboardName:pbName operationMask:opMask operation:op];
}
*/
@end